package com.wuming.common.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;

/**
 * 加密工具类
 * <p>用于对数据进行加密/解密,主要用于用户密码保护</p>
 *
 * @author 童天宇
 */
public class EncryptUtil {
    private static final String KEY = "bf5fa952d5ceb22a4d531eda976757721cec135f9be3dd46f7f16a547b4999cb";
    private static final String ALGORITHM = "HmacSHA256";

    /**
     * 加密
     * <p>抛出的异常有点多,且一般不会抛出,直接catch(Exception e)就好</p>
     *
     * @param data 待加密的数据(字符串)
     * @return 加密后的数据(字符串)
     * @throws IllegalArgumentException 参数错误
     * @throws InvalidKeyException      密钥无效
     * @throws NoSuchAlgorithmException 未找到加密算法
     */
    public static String encrypt(String data)
            throws IllegalArgumentException, InvalidKeyException, NoSuchAlgorithmException {
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("需加密内容不能为空");
        }
        Mac mac = Mac.getInstance(ALGORITHM);
        mac.init(new SecretKeySpec(KEY.getBytes(), ALGORITHM));
        byte[] rawHmac = mac.doFinal(data.getBytes());
        return HexFormat.of().formatHex(rawHmac);
    }

    /**
     * 验证
     * <p>这个加密算法不好解密,在这里采用判断加密后的数据是否与数据库存储的相匹配</p>
     *
     * @param data      需验证的数据
     * @param signature 数据库中存储的加密数据
     * @return 验证通过返回true，否则返回false
     * @throws IllegalArgumentException 参数错误
     * @throws InvalidKeyException      密钥无效
     * @throws NoSuchAlgorithmException 未找到加密算法
     */
    public static boolean verify(String data, String signature)
            throws IllegalArgumentException, InvalidKeyException, NoSuchAlgorithmException {
        if (data == null || data.isEmpty() || signature == null || signature.isEmpty()) {
            throw new IllegalArgumentException("参数不能为空");
        }
        String expectedSignature = encrypt(data);
        return expectedSignature.equals(signature);
    }
}
